"""
Core abstractions and interfaces for the Claude Code Theory framework.

This module defines the abstract interfaces and common functionality
that all components must implement, ensuring consistency across the framework.
"""

using LinearAlgebra
using Random
using Distributions

# ============================================================================
# Policy Abstractions
# ============================================================================

"""
    abstract type AbstractPolicy

Base type for all policies in the system.
"""
abstract type AbstractPolicy end

"""
    abstract type AbstractOption

Base type for hierarchical options in the system.
"""
abstract type AbstractOption end

"""
    select_action(policy::AbstractPolicy, state, context)

Select an action given the current state and context.
Must be implemented by all concrete policy types.
"""
function select_action end

"""
    update_policy!(policy::AbstractPolicy, experience)

Update the policy based on new experience.
Must be implemented by all learning policies.
"""
function update_policy! end

# ============================================================================
# Learning Abstractions
# ============================================================================

"""
    abstract type AbstractLearner

Base type for all learning algorithms in the system.
"""
abstract type AbstractLearner end

"""
    abstract type AbstractBandit <: AbstractLearner

Base type for bandit algorithms used in tool selection.
"""
abstract type AbstractBandit <: AbstractLearner end

"""
    select_arm(bandit::AbstractBandit, context::Vector{Float64})

Select an arm (tool) given the current context.
Returns the selected arm index and confidence score.
"""
function select_arm end

"""
    update_bandit!(bandit::AbstractBandit, arm::Int, reward::Float64, context::Vector{Float64})

Update the bandit model with observed reward.
"""
function update_bandit! end

"""
    get_regret_bound(bandit::AbstractBandit, horizon::Int, confidence::Float64)

Get theoretical regret bound for the bandit algorithm.
"""
function get_regret_bound end

# ============================================================================
# Context Management Abstractions
# ============================================================================

"""
    abstract type AbstractContextManager

Base type for context management systems.
"""
abstract type AbstractContextManager end

"""
    select_context(manager::AbstractContextManager, candidates, budget::Int)

Select optimal context subset under budget constraint.
Returns selected elements and approximation ratio achieved.
"""
function select_context end

"""
    update_context!(manager::AbstractContextManager, new_elements, feedback)

Update context management with new elements and performance feedback.
"""
function update_context! end

"""
    context_utility(manager::AbstractContextManager, subset)

Compute utility value for a context subset.
"""
function context_utility end

# ============================================================================
# Tool System Abstractions
# ============================================================================

"""
    abstract type AbstractToolExecutor

Base type for tool execution systems.
"""
abstract type AbstractToolExecutor end

"""
    abstract type AbstractToolRegistry

Base type for tool registries.
"""
abstract type AbstractToolRegistry end

"""
    execute_tool(executor::AbstractToolExecutor, action::ToolAction, state)

Execute a tool action in the given state.
Returns ToolExecutionResult and updated state.
"""
function execute_tool end

"""
    validate_parameters(registry::AbstractToolRegistry, tool::Tool, params)

Validate tool parameters against the tool's schema.
Returns true if valid, false otherwise with error details.
"""
function validate_parameters end

"""
    register_tool!(registry::AbstractToolRegistry, tool::Tool)

Register a new tool in the registry.
"""
function register_tool! end

"""
    get_compatible_tools(registry::AbstractToolRegistry, tool::Tool)

Get tools that can execute concurrently with the given tool.
"""
function get_compatible_tools end

# ============================================================================
# Concurrency Abstractions
# ============================================================================

"""
    abstract type AbstractQueueingModel

Base type for queueing theory models.
"""
abstract type AbstractQueueingModel end

"""
    abstract type AbstractMessageQueue

Base type for asynchronous message queues.
"""
abstract type AbstractMessageQueue end

"""
    stability_condition(model::AbstractQueueingModel)

Check if the queueing system satisfies stability conditions.
"""
function stability_condition end

"""
    expected_response_time(model::AbstractQueueingModel, load::Float64)

Compute expected response time for given system load.
"""
function expected_response_time end

"""
    enqueue!(queue::AbstractMessageQueue, message, priority::Float64=0.0)

Add message to the queue with optional priority.
"""
function enqueue! end

"""
    dequeue!(queue::AbstractMessageQueue)

Remove and return the highest priority message.
"""
function dequeue! end

# ============================================================================
# Safety and Verification Abstractions
# ============================================================================

"""
    abstract type AbstractSafetyChecker

Base type for safety verification systems.
"""
abstract type AbstractSafetyChecker end

"""
    abstract type AbstractRiskModel

Base type for risk assessment models.
"""
abstract type AbstractRiskModel end

"""
    assess_risk(model::AbstractRiskModel, state, action)

Assess the risk of taking an action in a given state.
Returns RiskAssessment with detailed risk breakdown.
"""
function assess_risk end

"""
    verify_safety(checker::AbstractSafetyChecker, state, action)

Verify if an action satisfies safety constraints.
Returns true if safe, false with violation details otherwise.
"""
function verify_safety end

"""
    safety_constraints(checker::AbstractSafetyChecker)

Get the set of safety constraints enforced by the checker.
"""
function safety_constraints end

# ============================================================================
# Evaluation Abstractions
# ============================================================================

"""
    abstract type AbstractMetrics

Base type for performance metrics systems.
"""
abstract type AbstractMetrics end

"""
    abstract type AbstractBenchmark

Base type for benchmark suites.
"""
abstract type AbstractBenchmark end

"""
    compute_metrics(metrics::AbstractMetrics, results)

Compute performance metrics from execution results.
"""
function compute_metrics end

"""
    run_benchmark(benchmark::AbstractBenchmark, system)

Run benchmark suite on the given system.
Returns comprehensive performance report.
"""
function run_benchmark end

"""
    statistical_significance(results1, results2, α::Float64=0.05)

Test for statistical significance between two result sets.
"""
function statistical_significance end

# ============================================================================
# Common Utility Functions
# ============================================================================

"""
    normalize_vector(v::Vector{Float64})

Normalize a vector to unit length, handling zero vectors gracefully.
"""
function normalize_vector(v::Vector{Float64})
    norm_v = norm(v)
    return norm_v > eps() ? v / norm_v : zeros(length(v))
end

"""
    softmax(x::Vector{Float64}, temperature::Float64=1.0)

Compute softmax with temperature parameter for exploration control.
"""
function softmax(x::Vector{Float64}, temperature::Float64=1.0)
    x_scaled = x / temperature
    x_max = maximum(x_scaled)
    exp_x = exp.(x_scaled .- x_max)  # numerical stability
    return exp_x / sum(exp_x)
end

"""
    confidence_interval(samples::Vector{Float64}, confidence::Float64=0.95)

Compute confidence interval for sample mean.
Returns (lower_bound, upper_bound).
"""
function confidence_interval(samples::Vector{Float64}, confidence::Float64=0.95)
    if length(samples) <= 1
        return (0.0, 0.0)
    end
    
    n = length(samples)
    mean_val = mean(samples)
    std_err = std(samples) / sqrt(n)
    
    # Use t-distribution for small samples
    if n < 30
        t_val = quantile(TDist(n-1), 1 - (1-confidence)/2)
    else
        t_val = quantile(Normal(), 1 - (1-confidence)/2)
    end
    
    margin = t_val * std_err
    return (mean_val - margin, mean_val + margin)
end

"""
    exponential_moving_average(current::Float64, new_value::Float64, α::Float64)

Update exponential moving average with new value.
"""
function exponential_moving_average(current::Float64, new_value::Float64, α::Float64)
    return α * new_value + (1 - α) * current
end

"""
    entropy(probabilities::Vector{Float64})

Compute Shannon entropy of a probability distribution.
"""
function entropy(probabilities::Vector{Float64})
    # Filter out zero probabilities to avoid log(0)
    p_nonzero = filter(p -> p > eps(), probabilities)
    return -sum(p -> p * log2(p), p_nonzero)
end

"""
    kl_divergence(p::Vector{Float64}, q::Vector{Float64})

Compute Kullback-Leibler divergence D(p||q).
"""
function kl_divergence(p::Vector{Float64}, q::Vector{Float64})
    @assert length(p) == length(q) "Probability vectors must have same length"
    
    divergence = 0.0
    for i in 1:length(p)
        if p[i] > eps() && q[i] > eps()
            divergence += p[i] * log(p[i] / q[i])
        elseif p[i] > eps() && q[i] <= eps()
            return Inf  # Divergence is infinite
        end
    end
    return divergence
end

"""
    information_gain(prior_entropy::Float64, posterior_entropy::Float64)

Compute information gain from belief update.
"""
function information_gain(prior_entropy::Float64, posterior_entropy::Float64)
    return max(0.0, prior_entropy - posterior_entropy)
end

"""
    weighted_average(values::Vector{Float64}, weights::Vector{Float64})

Compute weighted average of values.
"""
function weighted_average(values::Vector{Float64}, weights::Vector{Float64})
    @assert length(values) == length(weights) "Values and weights must have same length"
    
    total_weight = sum(weights)
    if total_weight <= eps()
        return 0.0
    end
    
    return sum(values .* weights) / total_weight
end

"""
    pareto_dominates(obj1::Vector{Float64}, obj2::Vector{Float64})

Check if objective vector obj1 Pareto dominates obj2.
"""
function pareto_dominates(obj1::Vector{Float64}, obj2::Vector{Float64})
    @assert length(obj1) == length(obj2) "Objective vectors must have same length"
    
    # obj1 dominates obj2 if it's >= in all dimensions and > in at least one
    all_geq = all(obj1[i] >= obj2[i] for i in 1:length(obj1))
    any_greater = any(obj1[i] > obj2[i] for i in 1:length(obj1))
    
    return all_geq && any_greater
end

"""
    pareto_frontier(objectives::Vector{Vector{Float64}})

Find Pareto frontier from a set of objective vectors.
Returns indices of non-dominated solutions.
"""
function pareto_frontier(objectives::Vector{Vector{Float64}})
    n = length(objectives)
    if n == 0
        return Int[]
    end
    
    frontier = Int[]
    
    for i in 1:n
        dominated = false
        for j in 1:n
            if i != j && pareto_dominates(objectives[j], objectives[i])
                dominated = true
                break
            end
        end
        
        if !dominated
            push!(frontier, i)
        end
    end
    
    return frontier
end

"""
    validate_probability_vector(p::Vector{Float64}, tolerance::Float64=1e-10)

Validate that vector represents a probability distribution.
"""
function validate_probability_vector(p::Vector{Float64}, tolerance::Float64=1e-10)
    # Check non-negativity
    if any(x < -tolerance for x in p)
        return false, "Negative probabilities found"
    end
    
    # Check normalization
    total = sum(p)
    if abs(total - 1.0) > tolerance
        return false, "Probabilities do not sum to 1.0 (sum = $total)"
    end
    
    return true, "Valid probability vector"
end

"""
    clip_to_range(x::Real, lower::Real, upper::Real)

Clip value to specified range.
"""
function clip_to_range(x::Real, lower::Real, upper::Real)
    return max(lower, min(upper, x))
end

"""
    safe_log(x::Real, base::Real=ℯ)

Logarithm with protection against numerical issues.
"""
function safe_log(x::Real, base::Real=ℯ)
    if x <= 0
        return -Inf
    end
    return log(base, x)
end

"""
    safe_sqrt(x::Real)

Square root with protection against negative inputs.
"""
function safe_sqrt(x::Real)
    return sqrt(max(0.0, x))
end